#include "xviewer.h"
#include "ui_XViewer.h"
#include "xcamera_config.h"
#include "xcamera_record.h"
#include "xcamera_widget.h"
#include "xplayvideo.h"
#include <QDialog>
#include <QFormLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QMessageBox>
#include <QMouseEvent>
#include <QTimerEvent>
#include <QVBoxLayout>
#include <Qdir>
#include <iostream>
#include <sstream>
#define CAM_CONF_PATH "cams.db"
#define C(x) QString::fromLocal8Bit(x)

using namespace std;

void XViewer::contextMenuEvent(QContextMenuEvent *ev) {
  // 鼠标位置显示右键菜单
  left_menu_->exec(QCursor::pos());
  ev->accept();
}
static XCameraWidget *cam_wids[16] = {0};

#define cam_wids_size (sizeof(cam_wids) / sizeof(QWidget *))

static vector<XCameraRecord *> records;

struct XCamVideo {
  QString filepath;
  QDateTime datetime;
};
static map<QDate, vector<XCamVideo>> cam_videos;

void XViewer::view(int count) {
  qDebug() << "View" << count;
  int cols = sqrt(count);
  int rows = cols;
  int wid_seze = cam_wids_size;
  //
  QGridLayout *lay = nullptr;
  lay = static_cast<QGridLayout *>(ui->cams->layout());
  if (!lay) {
    lay = new QGridLayout(ui->cams);
    lay->setContentsMargins(0, 0, 0, 0);
  }
  //
  int i = 0;
  for (; i < count; ++i) {
    if (!cam_wids[i]) {
      cam_wids[i] = new XCameraWidget(this);
      cam_wids[i]->setStyleSheet("background-color:rgb(51,51,51)");
    }
    lay->addWidget(cam_wids[i], i / rows, i % cols);
  }
  //
  for (; i < wid_seze; ++i) {
    if (cam_wids[i]) {
      delete cam_wids[i];
      cam_wids[i] = nullptr;
    }
  }
}

void XViewer::RefreshCams() {
  auto c = XCameraConfig::Instance();
  ui->cam_list->clear();
  int count = c->GetCamCount();
  for (int i = 0; i < count; ++i) {
    auto cam = c->GetCam(i);
    auto item =
        new QListWidgetItem(QIcon(":/img/cam.png"), C(cam.name), ui->cam_list);
    ui->cam_list->addItem(item);
  }
  c->Save(CAM_CONF_PATH);
}

void XViewer::SetCam(int index) {
  auto c = XCameraConfig::Instance();
  QDialog dlg(this);
  dlg.resize(800, 200);
  QFormLayout *lay = new QFormLayout(&dlg);
  QLineEdit *name_edit = new QLineEdit(&dlg);
  lay->addRow("名称", name_edit);
  QLineEdit *url_edit = new QLineEdit(&dlg);
  lay->addRow("主码流", url_edit);
  QLineEdit *suburl_edit = new QLineEdit(&dlg);
  lay->addRow("辅码流", suburl_edit);
  QLineEdit *save_path_edit = new QLineEdit(&dlg);
  lay->addRow("保存地址", save_path_edit);
  QPushButton *save_button = new QPushButton("保存", &dlg);
  lay->addRow("", save_button);
  QObject::connect(save_button, &QPushButton::clicked, &dlg, &QDialog::accept);
  if (index >= 0 && index < ui->cam_list->count()) { // 编辑 读入元数据显示
    auto cam = c->GetCam(index);
    name_edit->setText(C(cam.name));
    url_edit->setText(C(cam.url));
    suburl_edit->setText(C(cam.sub_url));
    save_path_edit->setText(C(cam.save_path));
  } else if (index == -1) { // 添加
  }
  auto f = [this, lay](QWidget *field) {
    QWidget *labelWidget = lay->labelForField(field);
    auto label = qobject_cast<QLabel *>(labelWidget);
    QMessageBox box;
    box.setIcon(QMessageBox::Information);
    box.setWindowTitle("提示");
    box.setText(QString("请输入%1").arg(label->text()));
    box.addButton(QMessageBox::Ok)->setText("确认");
    box.exec();
  };
  for (;;) {
    if (dlg.exec() == QDialog::Accepted) {
      if (name_edit->text().isEmpty()) {
        f(name_edit);
        continue;
      }
      if (url_edit->text().isEmpty()) {
        f(url_edit);
        continue;
      }
      if (suburl_edit->text().isEmpty()) {
        f(suburl_edit);
        continue;
      }
      if (save_path_edit->text().isEmpty()) {
        f(save_path_edit);
        continue;
      }
      break;
    }
    return;
  }
  XCameraData data;
  strcpy(data.name, name_edit->text().toLocal8Bit());
  strcpy(data.url, url_edit->text().toLocal8Bit());
  strcpy(data.sub_url, suburl_edit->text().toLocal8Bit());
  strcpy(data.save_path, save_path_edit->text().toLocal8Bit());
  if (index == -1) // 添加
    c->Push(data);
  else { // 修改
    c->SetCam(index, data);
  }
  c->Save(CAM_CONF_PATH);
  RefreshCams();
}

void XViewer::timerEvent(QTimerEvent *ev) {
  int wid_seze = cam_wids_size;
  for (int i = 0; i < wid_seze; i++) {
    if (cam_wids[i]) {
      cam_wids[i]->Draw();
    }
  }
}

XViewer::XViewer(QWidget *parent) : QWidget{parent} {
  ui = new Ui::XViewer();
  ui->setupUi(this);
  setWindowFlags(Qt::FramelessWindowHint);
  //
  QVBoxLayout *thisVLayout = new QVBoxLayout(this);
  thisVLayout->setContentsMargins(0, 0, 0, 0);
  thisVLayout->setSpacing(0);
  thisVLayout->addWidget(ui->head);
  thisVLayout->addWidget(ui->body);
  // 头部
  QHBoxLayout *headHLayout = new QHBoxLayout(ui->head);
  headHLayout->addWidget(ui->logo);
  headHLayout->addSpacing(9);
  QHBoxLayout *tabHLayout = new QHBoxLayout();
  tabHLayout->addWidget(ui->preview);
  tabHLayout->addWidget(ui->playback);
  tabHLayout->setAlignment(Qt::AlignBottom | Qt::AlignHCenter);
  headHLayout->addLayout(tabHLayout);
  headHLayout->addWidget(ui->status, 1);
  headHLayout->addWidget(ui->min);
  headHLayout->addWidget(ui->max);
  headHLayout->addWidget(ui->normal);
  headHLayout->addWidget(ui->close);
  headHLayout->setContentsMargins(0, 0, 15, 0);
  // 主体部分
  QHBoxLayout *bodyHLayout = new QHBoxLayout(ui->body);
  bodyHLayout->addWidget(ui->left);
  bodyHLayout->addWidget(ui->cams);
  bodyHLayout->addWidget(ui->playback_wid);
  connect(ui->normal, &QPushButton::clicked, this, &XViewer::NormalWindow);
  connect(ui->max, &QPushButton::clicked, this, &XViewer::MaxWindow);
  ui->normal->hide();
  ui->max->show();

  //
  left_menu_ = new QMenu(this);
  auto viewMenu = left_menu_->addMenu("视图");
  auto a = viewMenu->addAction("1窗口");
  connect(a, &QAction::triggered, this, &XViewer::view1);
  a = viewMenu->addAction("4窗口");
  connect(a, &QAction::triggered, this, &XViewer::view4);
  a = viewMenu->addAction("9窗口");
  connect(a, &QAction::triggered, this, &XViewer::view9);
  a = viewMenu->addAction("16窗口");
  connect(a, &QAction::triggered, this, &XViewer::view16);
  a = left_menu_->addAction("全部开始录制");
  connect(a, &QAction::triggered, this, &XViewer::StartRecord);
  a = left_menu_->addAction("全部停止录制");
  connect(a, &QAction::triggered, this, &XViewer::StopRecord);
  // 默认9个视图
  view(9);
  XCameraConfig::Instance()->Load(CAM_CONF_PATH);
  ui->time_list->clear();
  RefreshCams();
  //
  connect(ui->add_cam, &QPushButton::clicked, this, &XViewer::AddCam);
  connect(ui->set_cam, SIGNAL(clicked()), this, SLOT(SetCam()));
  connect(ui->del_cam, &QPushButton::clicked, this, &XViewer::DelCam);
  connect(ui->preview, &QPushButton::clicked, this, &XViewer::Preview);
  connect(ui->playback, &QPushButton::clicked, this, &XViewer::Playback);
  Preview();
  connect(ui->cam_list, &QListWidget::clicked, this, &XViewer::SelectCamera);
  connect(ui->cal, &XCalendar::clicked, this, &XViewer::SelectDate);
  connect(ui->time_list, &QListWidget::doubleClicked, this,
          &XViewer::PlayVideo);
  //
  startTimer(1);
}

XViewer::~XViewer() { delete ui; }
void XViewer::MaxWindow() {
  ui->normal->show();
  ui->max->hide();
  this->showMaximized();
}

void XViewer::NormalWindow() {
  ui->normal->hide();
  ui->max->show();
  this->showNormal();
}
void XViewer::view1() { view(1); }

void XViewer::view4() { view(4); }

void XViewer::view9() { view(9); }

void XViewer::view16() { view(16); }

void XViewer::AddCam() { SetCam(-1); }

void XViewer::SetCam() {
  int row = ui->cam_list->currentRow();
  if (row < 0) {
    QMessageBox::information(this, "提示", "前选择摄像机");
    return;
  }
  SetCam(row);
}

void XViewer::DelCam() {
  int row = ui->cam_list->currentRow();
  if (row < 0) {
    QMessageBox::information(this, "提示", "前选择摄像机");
    return;
  }
  std::stringstream ss;
  ss << "您确认要删除摄像机" << ui->cam_list->item(row)->text().toStdString()
     << "吗？";
  QString s = QString::fromStdString(ss.str());
  auto button = QMessageBox::question(this, "询问", s);
  if (button == QMessageBox::Yes) {
    auto c = XCameraConfig::Instance();
    c->DelCam(row);
    c->Save(CAM_CONF_PATH);
    RefreshCams();
  }
}

void XViewer::StartRecord() {
  StopRecord();
  ui->status->setText("正在录制...");
  // 获取录制列表
  auto conf = XCameraConfig::Instance();
  int count = conf->GetCamCount();
  QDir dir;
  for (int i = 0; i < count; i++) {
    auto cam = conf->GetCam(i);
    stringstream ss;
    ss << cam.save_path << "/" << i << "/";
    dir.mkpath(QString::fromStdString(ss.str()));
    XCameraRecord *record = new XCameraRecord();
    record->set_rtsp_url(cam.url);
    record->set_save_path(ss.str());
    record->set_file_sec(120);
    record->Start();
    records.push_back(record);
  }
  // 创建录制目录
  // 分别开始录制线程
}

void XViewer::StopRecord() {
  ui->status->setText("已停止录制");
  for (auto record : records) {
    record->Stop();
    delete record;
  }
  records.clear();
}

void XViewer::Preview() {
  ui->cams->show();
  ui->playback_wid->hide();
}

void XViewer::Playback() {
  ui->playback_wid->show();
  ui->cams->hide();
}

void XViewer::SelectCamera(const QModelIndex &index) {
  auto conf = XCameraConfig::Instance();
  auto data = conf->GetCam(index.row());
  if (data.name[0] == '\0') {
    return;
  }
  stringstream ss;
  ss << data.save_path << '/' << index.row() << '/';
  QDir dir(QString::fromStdString(ss.str()));
  if (!dir.exists())
    return;
  // 获取文件列表
  ui->cal->ClearDate();
  cam_videos.clear();
  QStringList fileters;
  fileters << "*.mp4" << "*.avi";
  auto files = dir.entryInfoList(fileters, QDir::Filter::Files |
                                               QDir::Filter::NoDotAndDotDot);
  for (auto &file : std::as_const(files)) {
    qDebug() << file.fileName();
    auto s = file.baseName();
    s = s.right(s.length() - 4);
    auto dateTime = QDateTime::fromString(s, "yyyy_MM_dd_hh_mm_ss");
    // qDebug() << dateTime.date();
    ui->cal->AddDate(dateTime.date());
    XCamVideo video;
    video.datetime = dateTime;
    video.filepath = file.absoluteFilePath();
    cam_videos[dateTime.date()].push_back(video);
  }
}

void XViewer::SelectDate(QDate date) {
  auto dates = cam_videos[date];
  ui->time_list->clear();
  for (auto &d : std::as_const(dates)) {
    auto item = new QListWidgetItem(d.datetime.time().toString());
    // 添加路径
    item->setData(Qt::UserRole, d.filepath);
    ui->time_list->addItem(item);
  }
}

void XViewer::PlayVideo(const QModelIndex &index) {
  auto item = ui->time_list->currentItem();
  if (!item)
    return;
  QString path = item->data(Qt::UserRole).toString();
  qDebug() << path;
  XPlayVideo play;
  play.Open(path.toStdString().c_str());
  play.exec();
}

////////////////////////////////////////
/// 鼠标拖动窗口事件
///
static bool mouse_press = false;
static QPointF mouse_point;

void XViewer::mouseMoveEvent(QMouseEvent *ev) {
  if (!mouse_press) {
    QWidget::mouseMoveEvent(ev);
  } else {
    this->move((ev->globalPosition() - mouse_point).toPoint());
  }
}

void XViewer::mousePressEvent(QMouseEvent *ev) {
  if (ev->button() == Qt::LeftButton) {
    mouse_press = true;
    mouse_point = ev->position();
  }
}

void XViewer::mouseReleaseEvent(QMouseEvent *ev) { mouse_press = false; }
